/*************************************************************************
	> File Name: job_v1.c
	> Author: Angel Criss
	> Mail: abbytsing@gmail.com 
	> Created Time: Sat, Jul 14, 2014  09:18:56 AM
 ************************************************************************/


/*
 * 在特定时间运行作为argv[0]参数的程序
 * 
 *  依赖: bin/tlpi/Exercise/ch-4/4-1 ; bin/tlpi/Exercise/ch-4/4-2
 *
 * grandfather  --running in a loop(wait timer expirate 6 times)-->run into a inifinity loop(waiting for a signal[pre-installed sighandler)
 *                     _______|______________________________                           |
 *                    |                   |                 |                           |
 *                    |                   |                 |                           |
 *                    |                   |                 |                   grandfater waits for SIGQUIT --------- argv[1] waits for argv[1]
 *                  creat father_1   creat father_2  creat fatehr_3                     |(SIGQUIT) -------------------------------> \ (SIGINT)
 *                  |CREAT CHILD          |CREAT CHILD      | the smae                  |                                         /   \
 *                  |(EXIT_SUCCESS)       |(EXIT_SUCCESS)   |the same           call sighandler(sigquit)                         /   killed (sighandler deal this as EXIT_SUCCESS)
 *                 /                      |                 |                           |                                       /
 *      child reaped by grandfather  child reaped       child reaped            call system() function              killed( because grandfather died then grandson die)
 *
 */

#include<unistd.h>
#include<signal.h>
#include<stdlib.h>
#include<sys/time.h>
#include<stdio.h>
#include<errno.h>

int _timer=0;

void err(char *func)
{
	perror(func);
	_exit(errno);
}

void dealing(int sig)
{
	if(sig==SIGALRM)
		_timer+=1;
	if(sig==SIGQUIT)
    {
	    printf("long running process end here\n");
        system("rm out-* tee.txt");  // remove extra files
        exit(EXIT_SUCCESS);
    }
}

int main(int argc,char *argv[])
{
	struct sigaction act;
	struct itimerval new_value;
    pid_t child;

	sigfillset(&act.sa_mask);
	act.sa_flags=SA_RESTART;
	act.sa_handler=dealing;

	new_value.it_interval.tv_sec=10; // reset timer in 10s
	new_value.it_interval.tv_usec=0;
	new_value.it_value.tv_sec=10; // timer expiration in 10s
	new_value.it_value.tv_usec=0;

	if(sigaction(SIGINT,&act,NULL)==-1) //这是个问题,在_timer<6时会屏蔽SIGINT使得\
        tee必须要在跳出for(;_timer<6;)之后才能被SIGINT杀死
		err("sigaction");
	if(sigaction(SIGALRM,&act,NULL)==-1)
		err("sigaction");
	if(sigaction(SIGCHLD,&act,NULL)==-1)
		err("sigaction");
	if(sigaction(SIGQUIT,&act,NULL)==-1)
		err("sigaction");

    if(setitimer(ITIMER_REAL,&new_value,NULL)==-1)
        err("setitimer");

	for(;;)
	{

		if(_timer==1)
        {
		        switch(fork())  // grandfather creats father
			    {
				    case -1:
					    err("fork");
				    case 0:
/*
 * 子进程不会继承父进程的间隔定时器
 * 这是的这个程序得以实现
 * exec()会继承进程标识、凭证 
*/
					    switch(fork()) // father creats son
                        {
                            case -1:
                                err("forkr(grandson)");
                            case 0:                             // this is son
                                //sleep(1);
                                child=getpid();
                                printf("exec tee command\n");
             			if(execl(argv[1],argv[1],"tee.txt",(char *)NULL)==-1)
                                    err("execl");
				             default:   // this is father
                            exit(EXIT_SUCCESS);  // father exit cause son reaped by grandfater
                        }
                    default:     // this is grandfather
                        wait(NULL);
                        break;   // grandfather wait father die
                }
        }    
        else if(_timer==3)
        {
			    switch(fork())  
			    {
				    case -1:
					    err("fork");
				    case 0:
					    switch(fork()) 
                        {
                            case -1:
                                err("forkr(grandson)");
                            case 0:                           
                                //sleep(2);
                                printf("write to out-2\n");
            			if(execl(argv[2],argv[2],"out-2","555555555",(char *)NULL)==-1)
                                   err("execl_2");
			    	        default:   
                            exit(EXIT_SUCCESS);  
                       }
                    default: 
                        wait(NULL);
                        break;  
                }
        }
        else if(_timer==5)
        {
			    switch(fork())  
			    {
				    case -1:
					    err("fork");
    				case 0:
	    				switch(fork()) 
                        {
                            case -1:
                                err("forkr(grandson)");
                            case 0:                      
                                //sleep(1);   
                                printf("write to out-3\n");	
            			if(execl(argv[2],argv[2],"out-3","555555555",(char *)NULL)==-1)
                                    err("execl_3");
    				        default:   
                            exit(EXIT_SUCCESS); 
                        }
                    default:     
                        wait(NULL);
                        break;  
                }
        }
        if(_timer<6)
        pause();
        else
        {
        //    kill(child,2); //使tee正常结束
        /*
         * 因为 4-1 这个子进程已经被 argv[0]这个祖父进程领养
         * 而 4-1这个程序中本身安装有对SIGINT的处理(模拟tee命令的ctrl+d)
         * 所以将上面的那句注释掉,程序执行到这儿ctrl+c即可
         */
            break;
        }
    }
    printf("[_timer] %d is up\n",_timer);
    for(;;)
    pause(); // waiting for ending signal(ctrl+\) 
}
